package com.xbk.seckill.common.utils.time;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 高性能时间戳获取工具类（通过后台线程缓存时间戳，减少系统调用开销）
 *
 * @author xiexu
 * @date 2025/2/4 11:16
 */
public class SystemClock {

    // 后台更新线程的名称（便于监控和调试）
    private static final String THREAD_NAME = "system.clock";

    /**
     * 单例实例：1毫秒更新一次时间戳的时钟对象
     * （MILLIS_CLOCK 是全局唯一的单例，保证所有线程共享同一个时间缓存）
     */
    private static final SystemClock MILLIS_CLOCK = new SystemClock(1);

    /**
     * 时间戳更新频率（单位：毫秒）
     */
    private final long precision;

    /**
     * 原子长整型变量，用于缓存当前时间戳
     */
    private final AtomicLong now;

    /**
     * 私有构造函数（强制通过静态工厂方法 millisClock() 获取实例）
     *
     * @param precision
     */
    private SystemClock(long precision) {
        this.precision = precision;
        // 初始化时获取当前系统时间戳作为初始值
        now = new AtomicLong(System.currentTimeMillis());
        // 启动后台线程定时更新时间戳
        scheduleClockUpdating();
    }

    public static SystemClock millisClock() {
        return MILLIS_CLOCK;
    }

    /**
     * 后台线程定时更新时间戳
     */
    private void scheduleClockUpdating() {
        // 创建单线程调度器（确保只有一个线程在更新时间戳）
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {
            Thread thread = new Thread(runnable, THREAD_NAME);
            // 设置为守护线程（当主线程退出时自动终止，避免内存泄漏）
            thread.setDaemon(true);
            return thread;
        });
        // 每隔precision毫秒更新时间戳
        scheduler.scheduleAtFixedRate(() -> now.set(System.currentTimeMillis()), precision, precision, TimeUnit.MILLISECONDS);
    }

    /**
     * 获取当前缓存的时间戳（高性能关键方法）
     *
     * @return
     */
    public long now() {
        return now.get();
    }

}
